﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace Core
{
    /// <summary>
    /// Http帮助类
    /// </summary>
    public static class HttpHelper
    {
        public static Dictionary<string, string> GetPage(String url)
        {
            Dictionary<string, string> param = new Dictionary<string, string>();
            try
            {
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                // Creates an HttpWebRequest for the specified URL.
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                // 有些网站会阻止程序访问，需要加入下面这句
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37";
                request.Method = "GET";
                // Sends the HttpWebRequest and waits for a response.
                HttpWebResponse res = (HttpWebResponse)request.GetResponse();
                if (res.StatusCode == HttpStatusCode.OK)
                {
                    param.Add("code", "1");
                    param.Add("msg", string.Format("Response Status Code is OK and StatusDescription is: {0}", res.StatusDescription));
                }
                // Releases the resources of the response.
                res.Close();
            }
            catch (WebException e)
            {
                param.Add("code", "0");
                param.Add("msg", string.Format("WebException Raised. The following error occured : {0}", e.Status));
            }
            catch (Exception e)
            {
                param.Add("code", "0");
                param.Add("msg", string.Format("The following Exception was raised : {0}", e.Message));
            }
            return param;
        }
        /// <summary>
        /// url为请求的网址，param参数为须要查询的条件（服务端接收的参数，没有则为null）
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string Get(string url, Dictionary<string, string> param = null, Dictionary<string, string> headers = null)
        {
            if (param != null) //有参数的状况下，拼接url
            {
                url = url + "?";
                url = param.Aggregate(url, (current, item) => current + item.Key + "=" + item.Value + "&");
                url = url.Substring(0, url.Length - 1);
            }
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            // 建立请求
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            // 请求方法为GET
            request.Method = "GET";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37";
            if (headers != null)
            {
                foreach (var item in headers)
                {
                    request.Headers[item.Key] = item.Value;
                }
            }
            // 定义返回的response
            HttpWebResponse res;
            try
            {
                // 此处发送了请求并得到响应
                res = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                res = (HttpWebResponse)ex.Response;
            }
            StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
            // 响应转化为String字符串
            string content = sr.ReadToEnd();
            sr.Close();
            return content;
        }

        /// <summary>
        /// url为请求的网址，param为须要传递的参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string Post(string url, Dictionary<string, string> param, Dictionary<string, string> headers = null)
        {
            string parameterSt = HttpHelper.GetParam(param);
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; //建立请求
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.AllowAutoRedirect = true;
            // request.AllowReadStreamBuffering = true;
            request.MaximumResponseHeadersLength = 1024;
            // 请求方式为:POST
            request.Method = "POST";
            request.AllowAutoRedirect = true;
            request.MaximumResponseHeadersLength = 1024;
            // 文档中所涉及的Http接口，在请求时，Content-Type 统一使用:Content-type:application/json;charset=UTF-8
            request.ContentType = "Content-type:application/json;charset=UTF-8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37";
            if (headers != null)
            {
                foreach (var item in headers)
                {
                    request.Headers[item.Key] = item.Value;
                }
            }

            Newtonsoft.Json.Linq.JObject json = new Newtonsoft.Json.Linq.JObject();
            // 将参数添加到json对象中
            if (param.Count != 0)
            {
                foreach (var item in param)
                {
                    json.Add(item.Key, item.Value);
                }
            }
            // 得到参数的json字符串
            string jsonstring = json.ToString();
            byte[] jsonbyte = Encoding.UTF8.GetBytes(jsonstring);
            Stream postStream = request.GetRequestStream();
            postStream.Write(jsonbyte, 0, jsonbyte.Length);
            postStream.Close();
            // 发送请求并获取相应回应数据 
            HttpWebResponse res;
            try
            {
                res = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                res = (HttpWebResponse)ex.Response;
            }
            StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
            // 得到响应字符串
            string content = sr.ReadToEnd();
            sr.Close();
            return content;
        }

        /// <summary>
        /// url为请求的网址，param为须要传递的参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string Post(string url, string postData)
        {
            // 支持https
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            // 建立请求
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.AllowAutoRedirect = true;
            request.MaximumResponseHeadersLength = 1024;
            request.Method = "POST";
            request.AllowAutoRedirect = true;
            request.MaximumResponseHeadersLength = 1024;
            request.ContentType = "Content-type:application/json;charset=UTF-8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37";
            byte[] jsonbyte = Encoding.UTF8.GetBytes(postData);
            Stream postStream = request.GetRequestStream();
            postStream.Write(jsonbyte, 0, jsonbyte.Length);
            postStream.Close();
            // 发送请求并获取相应回应数据
            HttpWebResponse res;
            try
            {
                res = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                res = (HttpWebResponse)ex.Response;
            }
            StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
            // 得到响应字符串
            string content = sr.ReadToEnd();
            sr.Close();
            return content;
        }

        /// <summary>
        /// url为请求的网址，param为须要传递的参数 返回文件类型数据
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <param name="paramStr"></param>
        /// <returns></returns>
        public static MemoryStream PostFile(string url, Dictionary<string, object> param, string paramStr = null)
        {
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            // 建立请求
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.AllowAutoRedirect = true;
            // request.AllowReadStreamBuffering = true;
            request.MaximumResponseHeadersLength = 1024;
            // 请求方式为:POST
            request.Method = "POST";
            request.AllowAutoRedirect = true;
            request.MaximumResponseHeadersLength = 1024;
            request.ContentType = "Content-type:application/json;charset=UTF-8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37";
            string jsonstring = string.Empty;
            if (string.IsNullOrEmpty(paramStr))
            {
                if (param != null)
                {
                    jsonstring = JsonConvert.SerializeObject(param);
                }
            }
            else
            {
                jsonstring = paramStr;
            }

            byte[] jsonbyte = Encoding.UTF8.GetBytes(jsonstring);
            Stream postStream = request.GetRequestStream();
            postStream.Write(jsonbyte, 0, jsonbyte.Length);
            postStream.Close();
            // 发送请求并获取相应回应数据 
            HttpWebResponse res;
            try
            {
                res = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                res = (HttpWebResponse)ex.Response;
            }
            Stream resultStream = res.GetResponseStream();
            MemoryStream ms = new MemoryStream();
            byte[] buffer = new byte[1024];
            while (true)
            {
                int sz = resultStream.Read(buffer, 0, 1024);
                if (sz == 0) break;
                ms.Write(buffer, 0, sz);
            }
            // string content = Encoding.UTF8.GetString(ms.ToArray()); 
            return ms;
        }
        /// <summary>
        /// url为请求的网址，param为须要传递的参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static string Post(string url, string param, Dictionary<string, string> headers = null)
        {
            string parameterSt = param;
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.AllowAutoRedirect = true;
            request.MaximumResponseHeadersLength = 1024;
            request.Method = "POST";
            request.AllowAutoRedirect = true;
            request.MaximumResponseHeadersLength = 1024;
            request.ContentType = "Content-type:application/json;charset=UTF-8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36 Edg/103.0.1264.37";
            if (headers != null)
            {
                foreach (var item in headers)
                {
                    request.Headers[item.Key] = item.Value;
                }
            }
            // 得到参数的json字符串
            string jsonstring = param;
            byte[] jsonbyte = Encoding.UTF8.GetBytes(jsonstring);
            Stream postStream = request.GetRequestStream();
            postStream.Write(jsonbyte, 0, jsonbyte.Length);
            postStream.Close();
            // 发送请求并获取相应回应数据 
            HttpWebResponse res;
            try
            {
                res = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                res = (HttpWebResponse)ex.Response;
            }
            StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
            // 得到响应字符串
            string content = sr.ReadToEnd();
            sr.Close();
            return content;
        }
        /// <summary>
        /// Http方式下载文件
        /// </summary>
        /// <param name="url">http地址</param>
        /// <param name="localfile">本地文件</param>
        /// <returns></returns>
        public static bool Download(string url, string localfile)
        {
            bool flag = false;
            // 上次下载的文件起始位置
            long startPosition = 0;
            // 写入本地文件流对象
            FileStream writeStream;
            // 被下载的文件名
            string fileName = url.Substring(url.LastIndexOf("/") + 1); ;
            // 另存为地址
            string path = localfile + fileName;
            // 判断要下载的文件夹是否存在
            if (File.Exists(path))
            {
                // 存在则打开要下载的文件
                writeStream = File.OpenWrite(path);
                // 获取已经下载的长度
                startPosition = writeStream.Length;
                // 本地文件写入位置定位
                writeStream.Seek(startPosition, SeekOrigin.Current);
            }
            else
            {
                // 文件不保存创建一个文件
                writeStream = new FileStream(path, FileMode.Create);
                startPosition = 0;
            }
            try
            {
                // 打开网络连接
                HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(url);
                if (startPosition > 0)
                {
                    // 设置Range值,与上面的writeStream.Seek用意相同,是为了定义远程文件读取位置
                    myRequest.AddRange((int)startPosition);
                }
                // 向服务器请求,获得服务器的回应数据流
                Stream readStream = myRequest.GetResponse().GetResponseStream();
                // 定义一个字节数据,用来向readStream读取内容和向writeStream写入内容
                byte[] btArray = new byte[512];
                // 向远程文件读第一次
                int contentSize = readStream.Read(btArray, 0, btArray.Length);
                // 如果读取长度大于零则继续读
                while (contentSize > 0)
                {
                    // 写入本地文件
                    writeStream.Write(btArray, 0, contentSize);
                    // 继续向远程文件读取
                    contentSize = readStream.Read(btArray, 0, btArray.Length);
                }
                // 关闭流
                writeStream.Close();
                readStream.Close();
                // 返回true下载成功
                flag = true;
            }
            catch (Exception)
            {
                writeStream.Close();
                // 返回false下载失败
                flag = false;
            }
            return flag;
        }
        /// <summary>
        /// 链接参数
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private static string GetParam(Dictionary<string, string> dic)
        {
            StringBuilder builder = new StringBuilder();
            int i = 0;
            foreach (var item in dic)
            {
                if (i > 0)
                {
                    builder.Append("&");
                }
                builder.AppendFormat("{0}={1}", item.Key, item.Value);
                i++;
            }
            return builder.ToString();
        }
        /// <summary>
        /// 链接参数
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private static string GetParam(Dictionary<string, object> dic)
        {
            StringBuilder builder = new StringBuilder();
            int i = 0;
            foreach (var item in dic)
            {
                if (i > 0)
                {
                    builder.Append("&");
                }
                builder.AppendFormat("{0}={1}", item.Key, item.Value);
                i++;
            }
            return builder.ToString();
        }
    }
}
